

import GlobalConstPkg from '../../common/globalConst.js'
var global = GlobalConstPkg.GlobalConst;

import { GlobalConstObj } from '../globalconstobj.js';

import LGXCOM from '../common.js'
import { LGXMathTool } from './math/lgxmathtool.js';

var UtilFuncs = {

}

UtilFuncs.group = function (fulltype) {
    var type = fulltype >> 24;
    return type;
}

UtilFuncs.mainObjType = function (fulltype) {
    var type = fulltype >> 16;
    return type;
}

UtilFuncs.isDimGraph = function (fulltype) {
    var type = fulltype >> 24;
    let flag = false;
    if (type == global.dimGroup) {
        flag = true;
    }
    return flag;
}

UtilFuncs.isMoldGraph32 = function (id) {
    var kind = id >> 16;
    return this.isMoldGraph16(kind);
}

UtilFuncs.isMoldGraph16 = function (nKind) {
    var flag = false;
    if (nKind == global.UMLMold
        || nKind == global.CommonBlock
        || nKind == global.SoftUICom) {
        flag = true;
    }
    return flag;
}

UtilFuncs.isLineDevEqp = function (fulltype) {
    var flag = false;
    var nKind = this.mainObjType(fulltype);
    if (nKind == global.ConnectLine || nKind == global.CommBusLine) {
        flag = true;
    }
    return flag;
}

UtilFuncs.isLineGraph = function (fulltype) {
    var flag = false;
    var nKind = this.mainObjType(fulltype);
    if (nKind == global.ConnectLine
        || nKind == global.CommBusLine
        || nKind == global.BaseUnitPolyline) {
        flag = true;
    }
    return flag;
}

UtilFuncs.distanceLineSec4Visual = function (pt, linePt1, linePt2, scaling) {
    let linesec = new LGXCOM.LGXLineSection();
    linesec.setPt(linePt1, linePt2);
    let interPoint = { x: 0, y: 0 };
    let dis = this.pt2LineSec(pt, linesec, interPoint);
    if (dis >= 0) {
        dis = dis * scaling;
    }
    else {
        let dis1 = this.distancePoint(pt, linePt1, scaling);
        let dis2 = this.distancePoint(pt, linePt2, scaling);
        dis = Math.min(dis1, dis2);
    }
    return dis;
}

UtilFuncs.distanceRayLine = function (pt, linePt1, linePt2, scaling) {
    let vector = this.getVector(linePt1, linePt2);
    let verticalVector = vector.rotateCopy(90);
    let interPt = this.getTwoLineInterPos(pt, verticalVector, linePt1, vector);
    let dis = this.distancePoint(pt, interPt, scaling);
    return { dis, pt: interPt };
}

UtilFuncs.distancePoint = function (pos1, pos2, scaling) {
    if (!scaling) {
        scaling = 1;
    }
    var lRst = Math.pow((pos1.x - pos2.x), 2) + Math.pow((pos1.y - pos2.y), 2);
    if (lRst >= 0) {
        lRst = Math.sqrt(lRst) * scaling;
    }
    return lRst;
}

UtilFuncs.adsorbPosOnLineSec = function (tPoint, pt1, pt2, scaling) {
    var a = pt1.x;
    var b = pt1.y;
    var c = pt2.x;
    var d = pt2.y;

    var x = tPoint.x;
    var y = tPoint.y;

    var lLen1 = this.distancePoint(tPoint, pt1, scaling);
    var lLen2 = this.distancePoint(tPoint, pt2, scaling);
    if ((lLen1 <= global.SelectGap) && (lLen1 < lLen2)) {
        tPoint.x = a;
        tPoint.y = b;
        return 1;
    }
    else if ((lLen2 <= global.SelectGap) && (lLen2 < lLen1)) {
        tPoint.x = c;
        tPoint.y = d;
        return 11;
    }

    var lRst;
    if (((d - b) == 0) &&
        (((x <= a) && (x >= c)) || ((x >= a) && (x <= c)))) {
        lRst = Math.abs(y - b);
        if (lRst <= global.SelectGap) {
            tPoint.y = b;
            return 10;
        }
        return 0;
    }
    else if (((a - c) == 0)
        && (((y <= b) && (y >= d)) || ((y >= b) && (y <= d)))) {
        lRst = Math.abs(x - a);
        if (lRst <= global.SelectGap) {
            tPoint.x = a;
            return 10;
        }
        return 0;
    }

    var nm = Math.pow((a - c), 2) / (d - b);
    var nConnX = nm * x + a * d - b * c - (a - c) * y;
    nConnX = nConnX / (d - b + nm);
    var nConnY = (a - c) / (d - b) * nConnX + y + (c - a) / (d - b) * x;

    var nSpecial = 0;
    if (((x >= a) && (x >= c)) && (a - c == 0)) {
        nSpecial = 1;
    }
    else if (((x <= a) && (x <= c)) && (a - c == 0)) {
        nSpecial = 1;
    }
    else if (((y >= b) && (y >= d)) && (b - d == 0)) {
        nSpecial = 1;
    }
    else if (((y <= b) && (y <= d)) && (b - d == 0)) {
        nSpecial = 1;
    }

    if ((((d - b) != 0) && ((a - c) != 0))
        && (((nConnX >= a) && (nConnX >= c))
            || ((nConnX <= a) && (nConnX <= c))
            || ((nConnY >= b) && (nConnY >= d)) || ((nConnY <= b) && (nConnY <= d)))) {
        nSpecial = 1;
    }

    if (nSpecial == 1) {
        lRst = this.distancePoint(tPoint, pt1, scaling);
        if (lRst <= global.SelectGap) {
            tPoint.x = a;
            tPoint.y = b;
            return 1;
        }
        lRst = this.distancePoint(tPoint, pt2, scaling);
        if (lRst <= global.SelectGap) {
            tPoint.x = c;
            tPoint.y = d;
            return 11;
        }
    }
    else if (((d - b) != 0) && ((a - c) != 0)) {
        lRst = Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));
        lRst = Math.abs((d - b) * x + (a - c) * y + (b * c - a * d)) / lRst;
        lRst = lRst * scaling;
        if (lRst <= global.SelectGap) {
            var k = (b - d) / (a - c);
            var x0 = tPoint.x;
            var y0 = tPoint.y;

            var interY = (k * x0 - k * c + d + k * k * y0) / (k * k + 1);
            var interX = (interY + k * c - d) / k;

            tPoint.x = interX;
            tPoint.y = interY;
            return 10;
        }
    }
    return 0;
}

UtilFuncs.rotate = function (pos, rotcnt, rotAngle) {
    var detax = (pos.x - rotcnt.x);
    var detay = (pos.y - rotcnt.y);
    var x = detax * Math.cos(rotAngle) - detay * Math.sin(rotAngle) + rotcnt.x;
    var y = detax * Math.sin(rotAngle) + detay * Math.cos(rotAngle) + rotcnt.y;
    return { x, y };
}

UtilFuncs.pointToRayLineDistance = function (point, rayLine) {
    let linePt1 = rayLine.stPt;
    let x = linePt1.x + rayLine.vector.m;
    let y = linePt1.y + rayLine.vector.n;
    let linePt2 = { x, y };
    return this.pointToLineDistance(point, linePt1, linePt2);
}

UtilFuncs.pointToLineDistance = function (point, lintpt1, lintpt2) {
    var dis = -1;
    var detax = lintpt1.x - lintpt2.x;
    var detay = lintpt1.y - lintpt2.y;
    if (Math.abs(detax) < global.ZERO_4E) {
        //参考线路为垂线,则直接求X坐标差值即可
        dis = Math.abs(point.x - lintpt1.x);
    }
    else {
        var ration = detay / detax;
        var A = ration;
        var B = -1;
        var C = lintpt1.y - ration * lintpt1.x;
        dis = this.pointToFormulaLineDis(point, A, B, C);
    }
    return dis;
}

UtilFuncs.pointToFormulaLineDis = function (point, A, B, C) {
    //直线方程：AX+BY+C = 0;
    var mod = Math.sqrt(A * A + B * B);
    var temp = Math.abs(A * point.x + B * point.y + C);
    var dis = temp / mod;
    return dis;
}

//求点pt到线linesec的距离，并把交点放interPoint返回
//函数返回值小于0标识交点不在线段上，无效
UtilFuncs.pt2LineSec = function (pt, linesec, interPoint) {
    let dis1 = this.distancePoint(pt, linesec.stPt, 1);
    let dis2 = this.distancePoint(pt, linesec.endPt, 1);
    if (dis1 < global.ZERO_4E) {
        interPoint.x = linesec.stPt.x;
        interPoint.y = linesec.stPt.y;
        return 0;
    }
    else if (dis2 < global.ZERO_4E) {
        interPoint.x = linesec.endPt.x;
        interPoint.y = linesec.endPt.y;
        return 0;
    }
    var minx = Math.min(linesec.stPt.x, linesec.endPt.x);
    var maxx = Math.max(linesec.stPt.x, linesec.endPt.x);
    var miny = Math.min(linesec.stPt.y, linesec.endPt.y);
    var maxy = Math.max(linesec.stPt.y, linesec.endPt.y);

    var x0 = linesec.stPt.x;
    var y0 = linesec.stPt.y;
    var detax = (linesec.stPt.x - linesec.endPt.x);
    var detay = (linesec.stPt.y - linesec.endPt.y);
    if (Math.abs(detax) < global.ZERO_4E) {
        //线路是垂直的，则pt到交点的连线为水平的
        interPoint.x = x0;
        interPoint.y = pt.y;
        if (pt.y < miny || pt.y > maxy) {
            //交点不在线段坐标范围内
            return -1;
        }
    }
    else if (Math.abs(detay) < global.ZERO_4E) {
        //线路是水平的，则pt到交点的连线为垂直的
        interPoint.y = y0;
        interPoint.x = pt.x;
        if (pt.x < minx || pt.x > maxx) {
            //交点不在线段坐标范围内
            return -1;
        }
    }
    else {
        //直线方程:y = k(x - x0) + b0;
        //垂线：
        //  k1 = -1/k
        //  y = k1(x - x1) + b1

        var k = detay / detax;
        var b0 = y0;

        var k1 = -1 / k;
        var x1 = pt.x;
        var b1 = pt.y;

        //k*x = k*x0 - b0;
        //k1*x = k1*x1 - b1;
        //(k - k1)*x = (k*x0 - b0 - k1*x1 + b1);
        var temp = k * x0 - b0 - k1 * x1 + b1;
        var x = temp / (k - k1);
        var y = k1 * (x - x1) + b1;

        interPoint.x = x;
        interPoint.y = y;
        if (x < minx || x > maxx) {
            //交点不在线段坐标范围内
            return -1;
        }
    }
    var dis = this.distancePoint(pt, interPoint, 1);
    return dis;
}




/*
         * kind = 1,水平线
         * kind = 2,垂直线
        */
UtilFuncs.chkHornVertKind = function (pt1, pt2) {
    var Vertical_LN = new LGXCOM.LGXVector();
    Vertical_LN.setValue(0, 1, 0);

    var Horizontal_LN = new LGXCOM.LGXVector();
    Horizontal_LN.setValue(1, 0, 0);

    const gap = 5;
    var kind = 0;
    var ldVt = new LGXCOM.LGXVector;
    ldVt.setBy2Pt(pt1, pt2);
    var angle2Horn = ldVt.angleToAnotherVector_Degree(Horizontal_LN);
    if (angle2Horn < gap) {
        kind = 1;
    }
    else {
        var angle2Vert = ldVt.angleToAnotherVector_Degree(Vertical_LN);
        if (angle2Vert < gap) {
            kind = 2;
        }
    }
    ldVt = null;
    return kind;
}

UtilFuncs.radian2Degree = function (fRadian) {
    return ((fRadian * 180) / Math.PI);
}

UtilFuncs.degree2Radian = function (degree) {
    return (degree * Math.PI) / 180.0;
}

UtilFuncs.generateUUID = function () {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = Math.random() * 16 | 0,
            v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}



UtilFuncs.isBaseUnit = function (fulltype) {
    let flag = false;
    let mainType = this.mainObjType(fulltype);
    switch (mainType) {
        case global.BaseUnitPolyline:
        case global.BaseUnitRectangle:
        case global.BaseUnitCircle:
        case global.BaseUnitPolygon:
        case global.BaseUnitArc:
        case global.BaseUnitChord:
        case global.BaseUnitPie:
        case global.BaseUnitEllipse:
        case global.QuadraticCurve:
        case global.BezierCurve:
        case global.BaseUnitText:
        case global.CubeType:
        case global.CylinderType:
        case global.SpecialRectType:
        case global.XMindType:
        case global.PathType:
            flag = true;
            break;
    }
    return flag;
}

UtilFuncs.isText = function (fulltype) {
    var flag = false;
    var nKind = this.mainObjType(fulltype);
    if (nKind == global.BaseUnitText || nKind == global.BaseUnitYCText) {
        flag = true;
    }
    return flag;
}

//求两条数学直线交点.四个坐标点描述
UtilFuncs.getTwoLineInterPos_4Point = function (line1Pt1, line1Pt2, line2Pt1, line2Pt2) {
    let lineVct1 = this.getVector(line1Pt1, line1Pt2);
    let lineVct2 = this.getVector(line2Pt1, line2Pt2);
    let interPoint = this.getTwoLineInterPos(line1Pt1, lineVct1, line2Pt1, lineVct2);
    return interPoint;
}

//求两条数学直线交点,起点坐标加向量描述线
UtilFuncs.getTwoLineInterPos = function (linePt1, lineVct1, linePt2, lineVct2) {
    if (lineVct1.parallel(lineVct2)) {
        return null;
    }
    let x1 = linePt1.x;
    let y1 = linePt1.y;
    let m1 = lineVct1.m;
    let n1 = lineVct1.n;

    let x2 = linePt2.x;
    let y2 = linePt2.y;
    let m2 = lineVct2.m;
    let n2 = lineVct2.n;

    //求线的参数k1,k2
    //x1 + k1*m1 = x2 + k2*m2
    //y1 + k1*n1 = y2 + k2*n2

    if (Math.abs(n1) < global.ZERO_8E) {
        //线1为垂直线,则两条线对调
        x1 = linePt2.x;
        y1 = linePt2.y;
        m1 = lineVct2.m;
        n1 = lineVct2.n;

        x2 = linePt1.x;
        y2 = linePt1.y;
        m2 = lineVct1.m;
        n2 = lineVct1.n;
    }

    let tm1 = (y1 * m1 / n1) - x1;
    let tm2 = x2 * (m1 / n1 - 1);
    let tm3 = (m2 * m1 / n1 - m2);
    let k2 = (tm1 - tm2) / tm3;

    let x = x2 + k2 * m2;
    let y = y2 + k2 * n2;
    let rstPt1 = { x, y };

    let rstPt2 = this.getTwoLineInterPos_ex(linePt1, lineVct1, linePt2, lineVct2);
    if (rstPt2 && (isNaN(rstPt2.x) || isNaN(rstPt2.y))) {
        // console.log("rstPt2 && (isNaN(rstPt2.x) ||isNaN(rstPt2.y)");
        // alert("rstPt2 && (isNaN(rstPt2.x) ||isNaN(rstPt2.y)");
        return null;
    }
    return rstPt2;
}

//求两条数学直线交点,起点坐标加向量描述线
UtilFuncs.getTwoLineInterPos_ex = function (linePt1, lineVct1, linePt2, lineVct2) {
    if (lineVct1.parallel(lineVct2)) {
        return false;
    }
    let x = 0;
    let y = 0;
    if (Math.abs(lineVct1.m) < global.ZERO_8E) {
        //线1为垂直线
        x = linePt1.x;
        let k2 = lineVct2.n / lineVct2.m;
        y = k2 * (x - linePt2.x) + linePt2.y;
    }
    else if (Math.abs(lineVct2.m) < global.ZERO_8E) {
        //线2为垂直线
        x = linePt2.x;
        let k1 = lineVct1.n / lineVct1.m;
        y = k1 * (x - linePt1.x) + linePt1.y;
    }
    else {
        let x1 = linePt1.x;
        let y1 = linePt1.y;
        let k1 = lineVct1.n / lineVct1.m;

        let x2 = linePt2.x;
        let y2 = linePt2.y;
        let k2 = lineVct2.n / lineVct2.m;

        let tm1 = k1 * x1 - y1 - k2 * x2 + y2;
        let tm2 = k1 - k2;
        if (Math.abs(tm2) < global.ZERO_8E) {
            console.log("");
        }
        x = tm1 / tm2;
        y = k1 * (x - x1) + y1;
        // if (x == Infinity || isNaN(x) || y == Infinity || isNaN(y)) {
        //     console.log("");
        // }
    }

    return { x, y };
}

UtilFuncs.chkOverlap = function (rect1, rect2) {
    if (rect1.posInRect(rect2.left, rect2.top)
        || rect1.posInRect(rect2.right, rect2.top)
        || rect1.posInRect(rect2.right, rect2.bottom)
        || rect1.posInRect(rect2.left, rect2.bottom)) {
        return true;
    }

    if (rect2.posInRect(rect1.left, rect1.top)
        || rect2.posInRect(rect1.right, rect1.top)
        || rect2.posInRect(rect1.right, rect1.bottom)
        || rect2.posInRect(rect1.left, rect1.bottom)) {
        return true;
    }
    let p1 = rect1.ltPt();
    let p2 = rect1.rtPt();
    let rst = this.chkLineSecInterRect(p1, p2, rect2);
    if (rst && rst.flag) {
        return true;
    }

    p1 = rect1.rtPt();
    p2 = rect1.rbPt();
    rst = this.chkLineSecInterRect(p1, p2, rect2);
    if (rst && rst.flag) {
        return true;
    }

    p1 = rect1.rbPt();
    p2 = rect1.lbPt();
    rst = this.chkLineSecInterRect(p1, p2, rect2);
    if (rst && rst.flag) {
        return true;
    }

    p1 = rect1.lbPt();
    p2 = rect1.ltPt();
    rst = this.chkLineSecInterRect(p1, p2, rect2);
    if (rst && rst.flag) {
        return true;
    }
    return false;
}

UtilFuncs.chkLineSecInterRect = function (linept1, linept2, rect) {
    let p1 = rect.ltPt();
    let p2 = rect.rtPt();
    let rst = this.chkTwoLineSecInter(p1, p2, linept1, linept2);
    if (rst && rst.flag) {
        return rst;
    }

    p1 = rect.rtPt();
    p2 = rect.rbPt();
    rst = this.chkTwoLineSecInter(p1, p2, linept1, linept2);
    if (rst && rst.flag) {
        return rst;
    }

    p1 = rect.rbPt();
    p2 = rect.lbPt();
    rst = this.chkTwoLineSecInter(p1, p2, linept1, linept2);
    if (rst && rst.flag) {
        return rst;
    }

    p1 = rect.lbPt();
    p2 = rect.ltPt();
    rst = this.chkTwoLineSecInter(p1, p2, linept1, linept2);
    if (rst && rst.flag) {
        return rst;
    }
    return null;
}

UtilFuncs.chkTwoLineSecInter = function (line1pt1, line1pt2, line2pt1, line2pt2) {
    let dis1 = this.distancePoint(line1pt1, line1pt2, 1);
    let dis2 = this.distancePoint(line2pt1, line2pt2, 1);
    if (dis1 < global.ZERO_4E || dis2 < global.ZERO_4E) {
        return null;
    }

    let vector1 = this.getVector(line1pt1, line1pt2);
    let vector2 = this.getVector(line2pt1, line2pt2);
    if (vector1.parallel(vector2)) {
        //两根线段平行，则检查其端点是否重合，若干重合也表示相交

        let stPtInter = false;
        let interPt1 = null;
        let dis3 = this.distancePoint(line1pt1, line2pt1, 1);
        let dis4 = this.distancePoint(line1pt1, line2pt2, 1);
        if (dis3 < global.ZERO_8E || dis4 < global.ZERO_8E) {
            stPtInter = true;
            interPt1 = { x: line1pt1.x, y: line1pt1.y };
        }

        let endPtInter = false;
        let interPt2 = null;
        let dis5 = this.distancePoint(line1pt2, line2pt1, 1);
        let dis6 = this.distancePoint(line1pt2, line2pt2, 1);
        if (dis5 < global.ZERO_8E || dis6 < global.ZERO_8E) {
            endPtInter = true;
            interPt2 = { x: line1pt2.x, y: line1pt2.y };
        }

        if (interPt1 && interPt2) {
            //完全重合，不相交
            return null;
        }
        else if (interPt1 && !interPt2) {
            return { flag: true, pt: interPt1 };
        }
        else if (!interPt1 && interPt2) {
            return { flag: true, pt: interPt2 };
        }
        else {
            return null;
        }
    }
    let interPoint = this.getTwoLineInterPos(line1pt1, vector1, line2pt1, vector2);
    if (!interPoint) {
        return null;
    }
    //检查交点是否在线段上
    let flag1 = this.chkPointOnLineSec(interPoint, line1pt1, line1pt2);
    let flag2 = this.chkPointOnLineSec(interPoint, line2pt1, line2pt2);
    if (!flag1 || !flag2) {
        return null;
    }
    else {
        return { flag: true, pt: interPoint };
    }
}

UtilFuncs.getVector = function (p1, p2) {
    let vct = new LGXCOM.LGXVector();
    vct.setBy2Pt(p1, p2);
    return vct;
}

//求某个点是否在线段上
UtilFuncs.chkPointOnLineSec = function (pt, linept1, linept2) {
    let dis1 = this.distancePoint(pt, linept1, 1);
    let dis2 = this.distancePoint(pt, linept2, 1);
    if (dis1 < global.ZERO_4E || dis2 < global.ZERO_4E) {
        return true;
    }
    let detax1 = pt.x - linept1.x;
    let detay1 = pt.y - linept1.y;

    let detax2 = pt.x - linept2.x;
    let detay2 = pt.y - linept2.y;
    if (Math.abs(detax1) < global.ZERO_8E && Math.abs(detax2) < global.ZERO_8E) {
        //垂直
        let miny = Math.min(linept1.y, linept2.y);
        let maxy = Math.max(linept1.y, linept2.y);
        if (pt.y >= miny && pt.y <= maxy) {
            return true;
        }
        else {
            return false;
        }
    }
    else if ((Math.abs(detax1) < global.ZERO_8E && Math.abs(detax2) > global.ZERO_8E)
        || (Math.abs(detax2) < global.ZERO_8E && Math.abs(detax1) > global.ZERO_8E)) {
        //一个垂直，一个不垂直，则肯定不在线上
        return false;
    }
    else {
        let k1 = detay1 / detax1;//段1斜率
        let k2 = detay2 / detax2;//段2斜率
        if (Math.abs(k1 - k2) > global.ZERO_8E) {
            //两端斜率不一样，肯定不在线上
            return false;
        }
    }

    //从当前点分别做向量到端点linept1和linept2，如果pt在两点之间，则向量的旋转角肯定等于180°
    let testVct1 = this.getVector(pt, linept1);
    let testVct2 = this.getVector(pt, linept2);
    let vct1Rot2vct2Angle = Math.abs(testVct1.angleByCrossMultiply2Another(testVct2));
    if (Math.abs(vct1Rot2vct2Angle - 180) < global.ZERO_8E) {
        return true;
    }
    else {
        return false;
    }
}


UtilFuncs.chkPtInArcSec = function (pArcPos, point) {
    let ptInfo = this.getArcControlPoint(pArcPos);
    let stVector = new LGXCOM.LGXVector();
    stVector.m = Math.cos(this.degree2Radian(pArcPos.stAngle));
    stVector.n = Math.sin(this.degree2Radian(pArcPos.stAngle));

    let endVector = new LGXCOM.LGXVector();
    endVector.m = Math.cos(this.degree2Radian(pArcPos.endAngle));
    endVector.n = Math.sin(this.degree2Radian(pArcPos.endAngle));

    let arcCNT = { x: pArcPos.x, y: pArcPos.y };
    let dstVector = new LGXCOM.LGXVector();
    dstVector.setBy2Pt(arcCNT, point);
    let testAngle = dstVector.angleFrmXAxisPositiveDir();

    //检查是否就在圆弧端点
    //设dstVector为圆心到当前点的向量
    //如果从起始线stVector到dstVector的旋转角度或者dstVector到起始线stVector的旋转角度足够接近于0，则认为就是端点
    let includeAngle11 = dstVector.angleByCrossMultiply2Another(stVector);
    let includeAngle12 = stVector.angleByCrossMultiply2Another(dstVector);
    if (Math.abs(includeAngle11) < global.ZERO_4E || Math.abs(includeAngle12) < global.ZERO_4E) {
        return true;
    }

    let includeAngle21 = dstVector.angleByCrossMultiply2Another(endVector);
    let includeAngle22 = endVector.angleByCrossMultiply2Another(dstVector);
    if (Math.abs(includeAngle21) < global.ZERO_4E || Math.abs(includeAngle22) < global.ZERO_4E) {
        return true;
    }

    let insecFlag = true;
    //如果从当前圆弧段起点到终点旋转角度小于圆弧段起点到当前鼠标在圆上投影点的旋转角度，则表示当前鼠标点不在本段内
    if (pArcPos.antiClockWise) {
        let st2EndAngle = stVector.angleByCrossMultiply2Another(endVector);
        let st2DstAngle = stVector.angleByCrossMultiply2Another(dstVector);
        if (st2DstAngle > st2EndAngle) {
            insecFlag = false;
        }
    }
    else {
        let end2StAngle = endVector.angleByCrossMultiply2Another(stVector);
        let endDstAngle = endVector.angleByCrossMultiply2Another(dstVector);
        if (endDstAngle > end2StAngle) {
            insecFlag = false;
        }
    }
    return insecFlag;
}

UtilFuncs.getArcStAndEndVector = function (pArcPos) {
    let stVector = new LGXCOM.LGXVector();
    stVector.m = Math.cos(this.degree2Radian(pArcPos.stAngle));
    stVector.n = Math.sin(this.degree2Radian(pArcPos.stAngle));

    let endVector = new LGXCOM.LGXVector();
    endVector.m = Math.cos(this.degree2Radian(pArcPos.endAngle));
    endVector.n = Math.sin(this.degree2Radian(pArcPos.endAngle));
    return { stVector, endVector };
}

UtilFuncs.getTwoLineSecInterPos = function (line1Pt1, line1Pt2, line2Pt1, line2Pt2) {
    let rstPt = null;
    let lineVct1 = this.getVector(line1Pt1, line1Pt2);
    let lineVct2 = this.getVector(line2Pt1, line2Pt2);
    let interPoint = this.getTwoLineInterPos(line1Pt1, lineVct1, line2Pt1, lineVct2);
    if (interPoint
        && this.chkPointOnLineSec(interPoint, line1Pt1, line1Pt2)
        && this.chkPointOnLineSec(interPoint, line2Pt1, line2Pt2)) {
        rstPt = interPoint;
    }
    return rstPt;
}

UtilFuncs.mirrorPoint = function (srcPt, mirrorAxisPos1, mirrorAxisPos2) {
    let x = srcPt.x;
    let y = srcPt.y;
    let x1 = mirrorAxisPos1.x;
    let y1 = mirrorAxisPos1.y;
    let x2 = mirrorAxisPos2.x;
    let y2 = mirrorAxisPos2.y;

    let xx = (2 * (x1 * y2 * y2 + x2 * y1 * y1 - (x1 + x2) * y1 * y2 - (x2 - x1) * y * y1 - (x1 - x2) * y * y2)
        + x * (this.variance(x1, x2) - this.variance(y1, y2)))
        / (this.variance(x1, x2) + this.variance(y1, y2));
    let yy = (2 * (x1 * x1 * y2 + x2 * x2 * y1 - x1 * x2 * (y1 + y2) - x * x1 * (y2 - y1) - x * x2 * (y1 - y2))
        + y * (this.variance(y1, y2) - this.variance(x1, x2)))
        / (this.variance(y1, y2) + this.variance(x1, x2));

    return { x: xx, y: yy };
}


//方差
UtilFuncs.variance = function (a, b) {
    return (a * a + b * b - 2 * a * b);
}

UtilFuncs.rotateAngle = function (ln1pt1, ln1pt2, ln2pt1, ln2pt2) {
    let vct1 = this.getVector(ln1pt1, ln1pt2);
    let vct2 = this.getVector(ln2pt1, ln2pt2);

    let stAngle = vct1.angleFrmXAxisPositiveDir();
    let endAngle = vct2.angleFrmXAxisPositiveDir();
    let rotAngle = endAngle - stAngle;
    return rotAngle;
}

UtilFuncs.getLineInterCircle = function (linept1, linept2, pCirclePos) {
    let circleCnt = pCirclePos.getCnt();
    let dis = this.pointToLineDistance(circleCnt, linept1, linept2);
    let detaDis = (dis - pCirclePos.radius);
    if (detaDis >= global.ZERO_4E) {
        return null;
    }

    let x1 = 0;
    let y1 = 0;
    let x2 = 0;
    let y2 = 0;

    let x0 = pCirclePos.x;
    let y0 = pCirclePos.y;
    let R = pCirclePos.radius;

    let detay = (linept1.y - linept2.y);
    let detax = (linept1.x - linept2.x);
    if (Math.abs(detax) < global.ZERO_8E) {
        //垂直
        let dis2cntX = Math.abs(x0 - linept1.x) - R;

        if (dis2cntX > 0 && Math.abs(dis2cntX) >= global.ZERO_4E) {
            return [];
        }
        else {
            x1 = linept1.x;
            x2 = linept1.x;
            let deta = (R * R - (x1 - x0) * (x1 - x0));
            if (Math.abs(deta) < global.ZERO_4E) {
                deta = 0;
            }
            let tmp = Math.sqrt(deta);
            y1 = y0 + tmp;
            y2 = y0 - tmp;
        }
    }
    else if (Math.abs(detay) < global.ZERO_8E) {
        //水平
        let dis2cntY = Math.abs(y0 - linept1.y) - R;
        if (dis2cntY > 0 && Math.abs(dis2cntY) >= global.ZERO_4E) {
            return [];
        }
        else {
            y1 = linept1.y;
            y2 = linept1.y;
            let deta = (R * R - (y1 - y0) * (y1 - y0));
            if (Math.abs(deta) < global.ZERO_4E) {
                deta = 0;
            }
            let tmp = Math.sqrt(deta);
            x1 = x0 + tmp;
            x2 = x0 - tmp;
        }
    }
    else {
        let k = (linept1.y - linept2.y) / (linept1.x - linept2.x);
        let a = linept1.y - k * linept1.x;

        let c = a - y0;
        let A = 1 + k * k;
        let B = 2 * k * c - 2 * x0;
        let C = x0 * x0 + c * c - R * R;
        let deta = B * B - 4 * A * C;
        if (deta < 0) {
            if (Math.abs(deta) > global.ZERO_4E) {
                return [];
            }
            else {
                deta = 0;
            }
        }
        x1 = (-B + Math.sqrt(deta)) / (2 * A);
        y1 = k * x1 + a;
        x2 = (-B - Math.sqrt(deta)) / (2 * A);
        y2 = k * x2 + a;
    }

    // console.log(x1);
    // console.log(y1);
    // console.log(x2);
    // console.log(y2);
    let rstArr = [];
    let interPoint1 = { x: x1, y: y1 };
    rstArr.push(interPoint1);
    let interPoint2 = { x: x2, y: y2 };
    rstArr.push(interPoint2);
    return rstArr;
}


UtilFuncs.calPtListZone = function (list) {
    var rect = new LGXCOM.LGXRect(0, 0, 0, 0);
    var lenth = list.length;
    var pt = list[0];
    rect.left = pt.x;
    rect.right = pt.x;
    rect.top = pt.y;
    rect.bottom = pt.y;

    for (var i = 1; i < lenth; i++) {
        pt = list[i];
        rect.left = Math.min(rect.left, pt.x);
        rect.right = Math.max(rect.right, pt.x);
        rect.bottom = Math.min(rect.bottom, pt.y);
        rect.top = Math.max(rect.top, pt.y);
    }
    return rect;
}

UtilFuncs.getCircleInterCircle = function (pCurentCirclePos, pToChkCirclePos) {
    let rstArr = [];

    let x0 = pCurentCirclePos.x;
    let y0 = pCurentCirclePos.y;
    let R0 = pCurentCirclePos.radius;

    let x1 = pToChkCirclePos.x;
    let y1 = pToChkCirclePos.y;
    let R1 = pToChkCirclePos.radius;

    let d = x0 * x0 - x1 * x1 + y0 * y0 - y1 * y1 + R1 * R1 - R0 * R0;
    let m = 2 * x1 - 2 * x0;
    let n = 2 * y1 - 2 * y0;
    if (Math.abs(n) < global.ZERO_8E) {
        let x = -d / m;
        let t1 = R0 * R0 - (x - x0) * (x - x0);
        if (Math.abs(t1) < global.ZERO_4E) {
            t1 = 0;
        }
        else if (t1 < 0) {
            //无交点
            return rstArr;
        }
        let y = y0 + Math.sqrt(t1);

        let interPoint1 = { x, y };
        let rst = { flag: true, pt: interPoint1 };
        rstArr.push(rst);

        y = y0 - Math.sqrt(t1);
        let interPoint2 = { x, y };
        let rst2 = { flag: true, pt: interPoint2 };
        rstArr.push(rst2);
    }
    else {
        let a = -d / n;
        let b = -m / n;

        let A = 1 + b * b;
        let B = -2 * y0 * b - 2 * x0 + 2 * a * b;
        let C = a * a + x0 * x0 - 2 * a * y0 + y0 * y0 - R0 * R0;
        let deta = B * B - 4 * A * C;
        if (Math.abs(deta) < global.ZERO_4E) {
            deta = 0;
        }
        else if (deta < 0) {
            //无交点
            return rstArr;
        }
        let x = (-B + Math.sqrt(deta)) / (2 * A);
        let y = a + b * x;
        let interPoint1 = { x, y };

        let rst = { flag: true, pt: interPoint1 };
        rstArr.push(rst);

        x = (-B - Math.sqrt(deta)) / (2 * A);
        y = a + b * x;
        let interPoint2 = { x, y };

        rst = { flag: true, pt: interPoint2 };
        rstArr.push(rst);
    }

    console.log(rstArr);
    return rstArr;
}



UtilFuncs.getArcControlPoint = function (postion) {
    let rst = this.getArcStAndEndVector(postion);
    // let arcSpanAngle = rst.stVector.angleByCrossMultiply2Another(rst.endVector);
    // if (!postion.antiClockWise) {
    //     arcSpanAngle = -rst.endVector.angleByCrossMultiply2Another(rst.stVector);
    // }
    let arcSpanAngle = this.getArcSpan(postion);
    let midVector = rst.stVector.rotateCopy(arcSpanAngle * 0.5);
    let stAngleRad = this.degree2Radian(postion.stAngle);
    let endAngleRad = this.degree2Radian(postion.endAngle);
    //起点
    let x = postion.x + postion.radius * Math.cos(stAngleRad);
    let y = postion.y + postion.radius * Math.sin(stAngleRad);
    let stPoint = { x, y };

    //中间点
    let midDotAngle = this.degree2Radian(midVector.angleFrmXAxisPositiveDir());
    x = postion.x + postion.radius * Math.cos(midDotAngle);
    y = postion.y + postion.radius * Math.sin(midDotAngle);
    let midPoint = { x, y };
    //终止点
    x = postion.x + postion.radius * Math.cos(endAngleRad);
    y = postion.y + postion.radius * Math.sin(endAngleRad);
    let endPoint = { x, y };
    return { stPoint, endPoint, midPoint };
}

UtilFuncs.getArcSpan = function (postion) {
    let rst = this.getArcStAndEndVector(postion);
    let arcSpanAngle = rst.stVector.angleByCrossMultiply2Another(rst.endVector);
    if (!postion.antiClockWise) {
        arcSpanAngle = -rst.endVector.angleByCrossMultiply2Another(rst.stVector);
    }
    return arcSpanAngle;
}


//计算某个点到某多段线坐标点的距离，以及所在多段线所在子段坐标点索引
//返回值为下面结构体
/*
{
    dis:   //最小距离
    stPosIdx:   //所在子段第一个坐标点索引
    endPosIdx:  //所在字段第二个坐标点索引
}
*/
UtilFuncs.getPointOnPolylineInfo = function (point, ptList, closeFlag) {
    let lenth = ptList.length;
    if (lenth < 2) {
        return null;
    }

    let stPosIdx = 0;   //所在子段第一个坐标点索引
    let endPosIdx = 0; //所在字段第二个坐标点索引
    let mindis = -1;

    let pCntPos = null;
    let pPrePos = ptList[0];
    for (var i = 0; i < lenth - 1; i++) {
        pCntPos = ptList[i + 1];
        let dis = this.distanceLineSec4Visual(point, pPrePos, pCntPos, 1);
        if (dis > 0) {
            if (mindis < 0) {
                stPosIdx = i;
                endPosIdx = i + 1;
                mindis = dis;
            }
            else if (mindis > dis) {
                stPosIdx = i;
                endPosIdx = i + 1;
                mindis = dis;
            }
        }
        pPrePos = pCntPos;
    }

    if (closeFlag) {
        pCntPos = ptList[0];
        let dis = this.distanceLineSec4Visual(point, pPrePos, pCntPos, 1);
        if (dis > 0) {
            if (mindis < 0) {
                stPosIdx = lenth - 1;
                endPosIdx = 0;
                mindis = dis;
            }
            else if (mindis > dis) {
                stPosIdx = lenth - 1;
                endPosIdx = 0;
                mindis = dis;
            }
        }
    }
    return { dis: mindis, stPosIdx, endPosIdx };
}


//计算圆上一点的与园相切的线向量，有两个，返回任意一个均可
UtilFuncs.getTangencyLine = function (pCirclePos, pt) {
    let cnt = pCirclePos.getCnt();
    let cnt2ptVct = this.getVector(cnt, pt);
    let dstVector = cnt2ptVct.rotateCopy(90);
    return dstVector;
}

UtilFuncs.calArcScope = function (pArcPos, mapscale) {
    let arcPtInfo = this.getArcControlPoint(pArcPos);
    let list = [];
    list.push(arcPtInfo.stPoint);
    list.push(arcPtInfo.midPoint);
    list.push(arcPtInfo.endPoint);

    //四个特征点是否在圆弧上
    let x = pArcPos.x + pArcPos.radius;
    let y = pArcPos.y;
    let tmpPt = { x, y };
    if (this.chkPtInArcSec(pArcPos, tmpPt)) {
        list.push(tmpPt);
    }

    x = pArcPos.x - pArcPos.radius;
    y = pArcPos.y;
    tmpPt = { x, y };
    if (this.chkPtInArcSec(pArcPos, tmpPt)) {
        list.push(tmpPt);
    }

    x = pArcPos.x;
    y = pArcPos.y + pArcPos.radius;
    tmpPt = { x, y };
    if (this.chkPtInArcSec(pArcPos, tmpPt)) {
        list.push(tmpPt);
    }

    x = pArcPos.x;
    y = pArcPos.y - pArcPos.radius;
    tmpPt = { x, y };
    if (this.chkPtInArcSec(pArcPos, tmpPt)) {
        list.push(tmpPt);
    }
    return this.calPtListZone(list);
}

UtilFuncs.chkLineSecInterRayLine = function (prePt, curentPt, rayLinept1, rayLinept2) {
    let vector1 = this.getVector(prePt, curentPt);
    let vector2 = this.getVector(rayLinept1, rayLinept2);
    if (vector1.parallel(vector2)) {
        console.log("two line parallel ******");
        return { flag: false, pt: null };
    }
    let interPoint = this.getTwoLineInterPos_ex(prePt, vector1, rayLinept1, vector2);
    if (!interPoint) {
        return { flag: false, pt: null };
    }
    //检查交点是否在线段上
    let flag1 = this.chkPointOnLineSec(interPoint, prePt, curentPt);
    if (!flag1) {
        return { flag: false, pt: null };
    }
    else {
        return { flag: true, pt: interPoint };
    }
}

UtilFuncs.chkLineSecInterRayLineByVector = function (linept1, linept2, rayPt, rayDir) {
    const nonInterRet = { flag: false, pt: null };
    let lineVct1 = this.getVector(linept1, linept2);
    if (lineVct1.parallel(rayDir)) {
        console.log("two line parallel ******");
        return nonInterRet;
    }
    let interPoint = this.getTwoLineInterPos_ex(linept1, lineVct1, rayPt, rayDir);
    if (!interPoint) {
        return nonInterRet;
    }
    let dis = this.distancePoint(interPoint, rayPt, 1);
    if (dis < global.ZERO_8E) {
        return nonInterRet;
    }

    //判断是否在射线方向上
    let rayStPt2InterPtVector = this.getVector(rayPt, interPoint);
    let rotAngle = rayStPt2InterPtVector.angleByCrossMultiply2Another(rayDir);
    if (Math.abs(rotAngle) > global.ZERO_4E) {
        return nonInterRet;
    }
    //检查交点是否在线段上
    let flag1 = this.chkPointOnLineSec(interPoint, linept1, linept2);
    if (!flag1) {
        return nonInterRet;
    }
    else {
        return { flag: true, pt: interPoint };
    }
}

UtilFuncs.chkPtOnRayLine = function (dstPt, rayPt, rayLineVector) {
    let dis = this.distancePoint(rayPt, dstPt, 1);
    if (dis < global.ZERO_4E) {
        return true;
    }
    let vct = this.getVector(rayPt, dstPt);
    let angle = vct.angleByCrossMultiply2Another(rayLineVector);
    if (Math.abs(angle) < global.ZERO_4E) {
        return true;
    }
    else {
        return false;
    }
}

UtilFuncs.getPointProj2Line = function (dstPt, linept, lineVector) {
    let verticalVector = lineVector.rotateCopy(90);
    let PtProj2Line = this.getTwoLineInterPos(dstPt, verticalVector, linept, lineVector);
    return PtProj2Line;
}

UtilFuncs.getMidPoint = function (p1, p2) {
    let x = (p1.x + p2.x) / 2;
    let y = (p1.y + p2.y) / 2;
    return { x, y };
}

UtilFuncs.chkPtInRect = function (pt, rect) {
    if (!pt || !rect) {
        return false;
    }
    let flag = false;
    const gap = global.ZERO_4E;
    if (pt.x > rect.right + gap
        || pt.x < rect.left - gap
        || pt.y <= rect.bottom - gap
        || pt.y >= rect.top + gap) {
        flag = false;
    }
    else {
        let p1 = rect.rtPt();
        let p2 = rect.rbPt();
        let vect = this.getVector(p1, p2);
        let interPt = this.getTwoLineInterPos(pt, GlobalConstObj.xAaxisVector, p1, vect);
        if (interPt) {
            let testVector = this.getVector(pt, interPt);
            let rotAngle = testVector.angleByCrossMultiply2Another(GlobalConstObj.xAaxisVector);
            if (Math.abs(rotAngle) < global.ZERO_4E) {
                flag = true;
            }
        }
    }
    return flag;
}

UtilFuncs.chkPtOnPolyline = function (point, ptlist, cmpGap, scaling) {
    var poscount = ptlist.length;
    if (poscount < 2) {
        return false;
    }
    let flag = false;
    let pPrePos = ptlist[0];
    for (var i = 1; i < poscount; i++) {
        let pCntPos = ptlist[i];
        let dis = this.distanceLineSec4Visual(point, pPrePos, pCntPos, scaling);
        if (dis >= 0 && dis < cmpGap) {
            flag = true;
            break;
        }
        pPrePos = pCntPos;
    }
    return flag;
}

UtilFuncs.chkAbsoluteHornVert = function (pt1, pt2) {
    let flag = false;
    let detax = Math.abs(pt1.x - pt2.x);
    let detay = Math.abs(pt1.y - pt2.y);
    if (detax < global.ZERO_4E || detay < global.ZERO_4E) {
        flag = true;
    }
    return flag;
}

UtilFuncs.getLineSecInterRectPoint = function (linept1, linept2, rect) {
    let p1 = rect.ltPt();
    let p2 = rect.rtPt();
    let interPtLst = [];
    let rst = this.chkTwoLineSecInter(p1, p2, linept1, linept2);
    if (rst && rst.flag) {
        interPtLst.push(rst.pt);
    }

    p1 = rect.rtPt();
    p2 = rect.rbPt();
    rst = this.chkTwoLineSecInter(p1, p2, linept1, linept2);
    if (rst && rst.flag) {
        interPtLst.push(rst.pt);
    }

    p1 = rect.rbPt();
    p2 = rect.lbPt();
    rst = this.chkTwoLineSecInter(p1, p2, linept1, linept2);
    if (rst && rst.flag) {
        interPtLst.push(rst.pt);
    }

    p1 = rect.lbPt();
    p2 = rect.ltPt();
    rst = this.chkTwoLineSecInter(p1, p2, linept1, linept2);
    if (rst && rst.flag) {
        interPtLst.push(rst.pt);
    }
    let result = null;
    if (interPtLst.length > 0) {
        let minDisPt = interPtLst[0];
        let mindis = this.distancePoint(linept1, minDisPt, 1);
        for (let i = 1; i < interPtLst.length; i++) {
            let pt = interPtLst[i];
            let dis = this.distancePoint(linept1, pt, 1);
            if (dis < mindis) {
                mindis = dis;
                minDisPt = pt;
            }
        }
        if (minDisPt) {
            result = { pt: minDisPt, dis: mindis, flag: true };
        }
    }
    return result;
}

UtilFuncs.removeCollapsePoint = function (ptlist) {
    let valiPtList = [];
    let count = ptlist.length;
    if (count == 2) {
        ptlist.forEach(pt => {
            valiPtList.push(pt);
        });
        return valiPtList;
    }
    valiPtList.push(ptlist[0]);
    for (let i = 1; i < count; i++) {
        let pt = ptlist[i];
        let prePt = valiPtList[valiPtList.length - 1];
        let dis = this.distancePoint(pt, prePt, 1);
        if (dis > global.ZERO_4E) {
            if (valiPtList.length == 1) {
                valiPtList.push(pt);
            }
            else {
                let prePrePt = valiPtList[valiPtList.length - 2];
                let preVct = this.getVector(prePrePt, prePt);
                let curentVct = this.getVector(prePt, pt);
                let includeAngle = preVct.angleToAnotherVector_Degree(curentVct);
                if (Math.abs(includeAngle) > global.ZERO_4E) {
                    valiPtList.push(pt);
                }
                else {
                    prePt.x = pt.x;
                    prePt.y = pt.y;
                }
            }
        }
    }
    return valiPtList;
}

UtilFuncs.convertRGBAStrToColor = function (colorStr) {
    let pos1 = colorStr.indexOf('(');
    let pos2 = colorStr.indexOf(')');
    var rgbaStr = colorStr.substr(pos1 + 1, pos2 - pos1 - 1);
    var rgbStrLst = rgbaStr.split(',');
    var lgxColor = new LGXCOM.LGXColor();
    lgxColor.red = parseInt(rgbStrLst[0]);
    lgxColor.green = parseInt(rgbStrLst[1]);
    lgxColor.blue = parseInt(rgbStrLst[2]);
    lgxColor.alpha = 255 * parseFloat(rgbStrLst[3]);

    return lgxColor
}

UtilFuncs.getLineInterEllipse = function (lineptIn1, lineptIn2, pEllipsePos) {
    let cntPt = pEllipsePos.getCnt();

    //转到局部坐标系下计算
    let localMtx = LGXMathTool.calLocalMatrix(cntPt, pEllipsePos.rotDegree);
    let localMtxInvert = localMtx.Inverse();
    let linept1 = localMtxInvert.MultT({ x: lineptIn1.x, y: lineptIn1.y, z: 0 });
    let linept2 = localMtxInvert.MultT({ x: lineptIn2.x, y: lineptIn2.y, z: 0 });

    //椭圆原点变换到标准坐标系原点
    cntPt.x = 0;
    cntPt.y = 0;
    let dis = this.pointToLineDistance(cntPt, linept1, linept2);
    let maxRadius = Math.max(pEllipsePos.xRadius, pEllipsePos.yRadius);
    let detaDis = (dis - maxRadius);
    if (detaDis >= global.ZERO_4E) {
        return null;
    }

    let p1 = { x: 0, y: 0 };
    let p2 = { x: 0, y: 0 };

    let x0 = linept1.x;
    let y0 = linept1.y;

    let x1 = cntPt.x;
    let y1 = cntPt.y;
    let A = pEllipsePos.xRadius;
    let B = pEllipsePos.yRadius;

    let pwA = A * A;
    let pwB = B * B;

    let detay = (linept1.y - linept2.y);
    let detax = (linept1.x - linept2.x);
    if (Math.abs(detax) < global.ZERO_8E) {
        //垂直
        let detaDis = (dis - pEllipsePos.xRadius);
        if (detaDis >= global.ZERO_4E) {
            return null;
        }
        p1.x = x0;
        p2.x = x0;

        let t1 = (x0 - x1) * (x0 - x1) / pwA;
        let t2 = Math.sqrt((1 - t1) * pwB);
        p1.y = y1 + t2;
        p2.y = y1 - t2;
    }
    else if (Math.abs(detay) < global.ZERO_8E) {
        //水平
        let detaDis = (dis - pEllipsePos.yRadius);
        if (detaDis >= global.ZERO_4E) {
            return null;
        }
        p1.y = y0;
        p2.y = y0;

        let t1 = (y0 - y1) * (y0 - y1) / pwB;
        let t2 = Math.sqrt((1 - t1) * pwA);
        p1.x = x1 + t2;
        p2.x = x1 - t2;
    }
    else {
        let k = detay / detax;
        let C = y0 - k * x0;


        let pwC = C * C;
        let pwx1 = x1 * x1;
        let pwy1 = y1 * y1;

        let a = pwB + pwA * k * k;
        let b = -(2 * pwB * x1 - 2 * pwA * k * C + 2 * pwA * k * y1);
        let c = pwB * pwx1 + pwA * pwC - 2 * pwA * C * y1 + pwA * pwy1 - pwA * pwB;

        let deta = b * b - 4 * a * c;
        if (deta < 0) {
            if (Math.abs(deta) > global.ZERO_4E) {
                return [];
            }
            else {
                deta = 0;
            }
        }
        p1.x = (-b + Math.sqrt(deta)) / (2 * a);
        p1.y = k * p1.x + C;

        p2.x = (-b - Math.sqrt(deta)) / (2 * a);
        p2.y = k * p2.x + C;
    }

    //交点变换到世界坐标系下返回
    let worldInterPt1 = localMtx.MultT({ x: p1.x, y: p1.y, z: 0 });
    let worldInterPt2 = localMtx.MultT({ x: p2.x, y: p2.y, z: 0 });
    let rstArr = [];
    rstArr.push(worldInterPt1);
    rstArr.push(worldInterPt2);
    return rstArr;
}

UtilFuncs.getLineInterEllipseArc = function (linept1, linept2, pEllipsePos) {
    let circleCnt = pEllipsePos.getCnt();
    let dis = this.pointToLineDistance(circleCnt, linept1, linept2);
    let maxRadius = Math.max(pEllipsePos.yRadius, pEllipsePos.xRadius);
    let detaDis = (dis - maxRadius);
    if (detaDis >= global.ZERO_4E) {
        return null;
    }

    let p1 = { x: 0, y: 0 };
    let p2 = { x: 0, y: 0 };

    let x0 = linept1.x;
    let y0 = linept1.y;

    let x1 = pEllipsePos.x;
    let y1 = pEllipsePos.y;
    let A = pEllipsePos.xRadius;
    let B = pEllipsePos.yRadius;

    let pwA = A * A;
    let pwB = B * B;

    let detay = (linept1.y - linept2.y);
    let detax = (linept1.x - linept2.x);
    if (Math.abs(detax) < global.ZERO_8E) {
        //垂直
        let detaDis = (dis - pEllipsePos.xRadius);
        if (detaDis >= global.ZERO_4E) {
            return null;
        }
        p1.x = x0;
        p2.x = x0;

        let t1 = (x0 - x1) * (x0 - x1) / pwA;
        let t2 = Math.sqrt((1 - t1) * pwB);
        p1.y = y1 + t2;
        p2.y = y1 - t2;
    }
    else if (Math.abs(detay) < global.ZERO_8E) {
        //水平
        let detaDis = (dis - pEllipsePos.yRadius);
        if (detaDis >= global.ZERO_4E) {
            return null;
        }
        p1.y = y0;
        p2.y = y0;

        let t1 = (y0 - y1) * (y0 - y1) / pwB;
        let t2 = Math.sqrt((1 - t1) * pwA);
        p1.x = x1 + t2;
        p2.x = x1 - t2;
    }
    else {
        let k = detay / detax;
        let C = y0 - k * x0;


        let pwC = C * C;
        let pwx1 = x1 * x1;
        let pwy1 = y1 * y1;

        let a = pwB + pwA * k * k;
        let b = -(2 * pwB * x1 - 2 * pwA * k * C + 2 * pwA * k * y1);
        let c = pwB * pwx1 + pwA * pwC - 2 * pwA * C * y1 + pwA * pwy1 - pwA * pwB;

        let deta = b * b - 4 * a * c;
        if (deta < 0) {
            if (Math.abs(deta) > global.ZERO_4E) {
                return [];
            }
            else {
                deta = 0;
            }
        }
        p1.x = (-b + Math.sqrt(deta)) / (2 * a);
        p1.y = k * p1.x + C;

        p2.x = (-b - Math.sqrt(deta)) / (2 * a);
        p2.y = k * p2.x + C;
    }

    let rstArr = [];
    rstArr.push(p1);
    rstArr.push(p2);
    return rstArr;
}


UtilFuncs.getEllipseArcControlPoint = function (postion) {
    let rst = this.getArcStAndEndVector(postion);
    let arcSpanAngle = rst.stVector.angleByCrossMultiply2Another(rst.endVector);
    if (!postion.antiClockWise) {
        arcSpanAngle = -rst.endVector.angleByCrossMultiply2Another(rst.stVector);
    }
    let midVector = rst.stVector.rotateCopy(arcSpanAngle * 0.5);
    let stAngleRad = this.degree2Radian(postion.stAngle);
    let endAngleRad = this.degree2Radian(postion.endAngle);
    //起点
    let x = postion.x + postion.xRadius * Math.cos(stAngleRad);
    let y = postion.y + postion.yRadius * Math.sin(stAngleRad);
    let stPoint = { x, y };

    //中间点
    let midDotAngle = this.degree2Radian(midVector.angleFrmXAxisPositiveDir());
    x = postion.x + postion.xRadius * Math.cos(midDotAngle);
    y = postion.y + postion.yRadius * Math.sin(midDotAngle);
    let midPoint = { x, y };
    //终止点
    x = postion.x + postion.xRadius * Math.cos(endAngleRad);
    y = postion.y + postion.yRadius * Math.sin(endAngleRad);
    let endPoint = { x, y };
    return { stPoint, endPoint, midPoint };
}

UtilFuncs.calEllipseArcScope = function (pArcPos, mapscale) {
    let arcPtInfo = this.getEllipseArcControlPoint(pArcPos);
    let list = [];
    list.push(arcPtInfo.stPoint);
    list.push(arcPtInfo.midPoint);
    list.push(arcPtInfo.endPoint);

    //四个特征点是否在圆弧上
    let x = pArcPos.x + pArcPos.xRadius;
    let y = pArcPos.y;
    let tmpPt = { x, y };
    if (this.chkPtInEllipseArcSec(pArcPos, tmpPt)) {
        list.push(tmpPt);
    }

    x = pArcPos.x - pArcPos.xRadius;
    y = pArcPos.y;
    tmpPt = { x, y };
    if (this.chkPtInEllipseArcSec(pArcPos, tmpPt)) {
        list.push(tmpPt);
    }

    x = pArcPos.x;
    y = pArcPos.y + pArcPos.yRadius;
    tmpPt = { x, y };
    if (this.chkPtInEllipseArcSec(pArcPos, tmpPt)) {
        list.push(tmpPt);
    }

    x = pArcPos.x;
    y = pArcPos.y - pArcPos.yRadius;
    tmpPt = { x, y };
    if (this.chkPtInEllipseArcSec(pArcPos, tmpPt)) {
        list.push(tmpPt);
    }
    return this.calPtListZone(list);
}


UtilFuncs.chkPtInEllipseArcSec = function (pArcPos, point) {
    let ptInfo = this.getEllipseArcControlPoint(pArcPos);
    let arcCNT = { x: pArcPos.x, y: pArcPos.y };

    let stVector = new LGXCOM.LGXVector();
    stVector.setBy2Pt(arcCNT, ptInfo.stPoint);

    let endVector = new LGXCOM.LGXVector();
    endVector.setBy2Pt(arcCNT, ptInfo.endPoint);

    let dstVector = new LGXCOM.LGXVector();
    dstVector.setBy2Pt(arcCNT, point);
    let testAngle = dstVector.angleFrmXAxisPositiveDir();

    //检查是否就在圆弧端点
    //设dstVector为圆心到当前点的向量
    //如果从起始线stVector到dstVector的旋转角度或者dstVector到起始线stVector的旋转角度足够接近于0，则认为就是端点
    let includeAngle11 = dstVector.angleByCrossMultiply2Another(stVector);
    let includeAngle12 = stVector.angleByCrossMultiply2Another(dstVector);
    if (Math.abs(includeAngle11) < global.ZERO_4E || Math.abs(includeAngle12) < global.ZERO_4E) {
        return true;
    }

    let includeAngle21 = dstVector.angleByCrossMultiply2Another(endVector);
    let includeAngle22 = endVector.angleByCrossMultiply2Another(dstVector);
    if (Math.abs(includeAngle21) < global.ZERO_4E || Math.abs(includeAngle22) < global.ZERO_4E) {
        return true;
    }

    let insecFlag = true;
    //如果从当前圆弧段起点到终点旋转角度小于圆弧段起点到当前鼠标在圆上投影点的旋转角度，则表示当前鼠标点不在本段内
    if (pArcPos.antiClockWise) {
        let st2EndAngle = stVector.angleByCrossMultiply2Another(endVector);
        let st2DstAngle = stVector.angleByCrossMultiply2Another(dstVector);
        if (st2DstAngle > st2EndAngle) {
            insecFlag = false;
        }
    }
    else {
        let end2StAngle = endVector.angleByCrossMultiply2Another(stVector);
        let endDstAngle = endVector.angleByCrossMultiply2Another(dstVector);
        if (endDstAngle > end2StAngle) {
            insecFlag = false;
        }
    }
    return insecFlag;
}

//求无限长直线与目标矩形的交点，要么0个，要么两个
UtilFuncs.getLineInterRect = function (linept1, linept2, rect) {
    if (rect.width() < global.ZERO_8E || rect.height() < global.ZERO_8E) {
        return [];
    }
    let p1 = rect.ltPt();
    let p2 = rect.rtPt();
    let interPtLst = [];
    let interPt = this.getTwoLineInterPos_4Point(p1, p2, linept1, linept2);
    if (interPt && this.chkPointOnLineSec(interPt, p1, p2)) {
        interPtLst.push(interPt);
    }

    p1 = rect.rtPt();
    p2 = rect.rbPt();
    interPt = this.getTwoLineInterPos_4Point(p1, p2, linept1, linept2);
    if (interPt && this.chkPointOnLineSec(interPt, p1, p2)) {
        interPtLst.push(interPt);
    }

    p1 = rect.rbPt();
    p2 = rect.lbPt();
    interPt = this.getTwoLineInterPos_4Point(p1, p2, linept1, linept2);
    if (interPt && this.chkPointOnLineSec(interPt, p1, p2)) {
        interPtLst.push(interPt);
    }

    p1 = rect.lbPt();
    p2 = rect.ltPt();
    interPt = this.getTwoLineInterPos_4Point(p1, p2, linept1, linept2);
    if (interPt && this.chkPointOnLineSec(interPt, p1, p2)) {
        interPtLst.push(interPt);
    }
    let validList = [];
    if (interPtLst.length > 0) {
        //去掉几乎重叠的交点，如线路正好与矩形边相交在顶点
        let prePt = interPtLst[0];
        validList.push(prePt);
        for (let i = 1; i < interPtLst.length; i++) {
            let pt = interPtLst[i];
            let dis = this.distancePoint(prePt, pt, 1);
            if (dis > global.ZERO_8E) {
                validList.push(pt);
                prePt = pt;
            }
        }
        if (validList.length == 2) {
            let srcVect = this.getVector(linept1, linept2);
            let pt1 = validList[0];
            let pt2 = validList[1];
            let dstVect = this.getVector(pt1, pt2);
            let includeAngle = dstVect.angleByCrossMultiply2Another(srcVect);
            if (Math.abs(includeAngle) > global.ZERO_4E) {
                //交点顺序调整，保持第一个交点到第二个交点的向量与原直线向量一致
                validList = [];
                validList.push(pt2);
                validList.push(pt1);
            }
        }
        else {
            validList = [];
        }
    }
    return validList;
}

UtilFuncs.chkRectInRect = function (srcRect, dstRect) {
    if (srcRect.left > dstRect.right
        || srcRect.right < dstRect.left
        || srcRect.bottom > dstRect.top
        || srcRect.top < dstRect.bottom) {
        return false;
    }
    else {
        return true;
    }
}

export default { UtilFuncs }